#ifndef NANE_ISOUNDSYSTEM_H
#   define NANE_ISOUNDSYSTEM_H

#   include "nane/core/types.h"
#   include "nane/core/enum.h"
#   include "nane/core/ISubSystem.h"

namespace nane
{
    struct ESoundFormat
        : public Enum<ESoundFormat>
    {
        enum domain
        {
            PCM = 0,
            ADPCM,
            xWMA,
            XMA,
            _max
        };
        
        NANE_ENUM( ESoundFormat, Enum );
    };
    
    struct ISoundBuffer
    {
    };
    
    struct ISoundSource
    {
    };
    
    struct ISoundSource3D
        : public ISoundSource
    {
    };
    
    struct ISoundSystem
        : public ISubSystem
    {
        // context must not be initialized
        virtual bool InitializeContext( float _speedOfSound ) = 0;
        
        // context must be initialized and all buffers and source must be released
        virtual void ShutdownContext() = 0;
        
        //
        // creates sound buffer
        // -
        // precond:
        //   ISoundSystem context must be initialized
        // params:
        //   _format - data format
        //   _frequency - sound frequency
        //   _channels - number of channels
        //   _bitsPerSample - bits per sample
        //   _size - size of sound buffer to create in bytes
        // result:
        //   returns non-null ISoundBuffer interface pointer if buffer was successfully created, otherwise - null
        //   non-null ISoundBuffer pointer must be released with 'ReleaseSoundBuffer' before SubSystem shutdown
        //
        virtual ISoundBuffer* CreateSoundBuffer( ESoundFormat::raw_type _format, uint32 _frequency, uint16 _channels
                                                , uint16 _bitsPerSample, uint32 _size ) = 0;


        virtual byte* LockSoundBuffer( ISoundBuffer* _buffer ) = 0;
        virtual void UnlockSoundBuffer( ISoundBuffer* _buffer ) = 0;

        //
        // releases previously created sound buffer
        // -
        // precond:
        //   ISoundSystem context must be initialized
        //   sound buffer being released must not be queued in any of sound sources
        // params:
        //   _soundBuffer - non-null valid ISoundBuffer pointer returned by 'CreateSoundBuffer'
        // results:
        //   all resources assigned with ISoundBuffer are released
        //
        virtual void ReleaseSoundBuffer( ISoundBuffer* _soundBuffer ) = 0;
        
        //
        // creates simple sound source
        // -
        // precond:
        //   ISoundSystem context must be initialized
        // resutls:
        //   returns non-null ISoundSource interface pointer on success, otherwise - null
        //   non-null ISoundSource pointer must be released with 'ReleaseSoundSource' before context shutdown
        //
        virtual ISoundSource* CreateSoundSource() = 0;


        virtual void SetListenerPosition( float _x, float _y, float _z ) = 0;
        virtual void SetListenerOrientation( float _atX, float _atY, float _atZ, float _upX, float _upY, float _upZ ) = 0;
        virtual void SetListenerVelocity( float _x, float _y, float _z ) = 0;

        //
        // creates 3D sound source
        // -
        // precond:
        //   ISoundSystem context must be initialized
        // results:
        //   returns non-null ISoundSource3D interface pointer on success, otherwise - null
        //   non-null ISoundSource3D pointer must be released with 'ReleaseSoundSource' before context shutdown
        //
        virtual ISoundSource3D* CreateSoundSource3D() = 0;

        //
        // set position of 3D sound source
        // -
        // precond:
        //   ISoundSystem context must be initialized
        // params:
        //   _source - non-null valid ISoundSource3D interface pointer to set position of
        //   _x, _y, _z - position
        // results:
        //   position of sound source is changed
        //
        virtual void SetSource3DPosition( ISoundSource3D* _source, float _x, float _y, float _z ) = 0;

        //
        // set velocity of 3D sound source
        // -
        // precond:
        //   ISoundSystem context must be initialized
        // params:
        //   _source - non-null valid ISoundSource3D interface pointer to set position of
        //   _x, _y, _z - velocity
        // results:
        //   velocity of sound source is changed
        //
        virtual void SetSource3DVelocity( ISoundSource3D* _source, float _x, float _y, float _z ) = 0;


        virtual bool QueueSourceBuffer( ISoundSource* _source, ISoundBuffer* _buffer ) = 0;
        virtual uint32 GetSourceBuffersQueued( ISoundSource* _source ) = 0;
        virtual void ClearSourceBufferQueue( ISoundSource* _source ) = 0;
        
        //
        // turns sound source into 'playing' state
        // -
        // precond:
        //   ISoundSystem context must be initialized
        //   sound source must be in 'stopped' state
        // params:
        //   _source - non-null valid ISoundSource pointer to change state of
        //   _posMs - position to play from in milliseconds
        // results:
        //   _source state is changed to 'playing'
        //
        virtual void Play( ISoundSource* _source, uint32 _posMs ) = 0;
        
        //
        // turns sound source into 'stopped' state
        // -
        // precond:
        //   ISoundSystem context must be initialized
        //   sound source must be in 'playing' state
        // params:
        //   _source - non-null valid ISoundSource pointer to change state of
        // results:
        //   _source state is changed to 'stopped'
        //
        virtual void Stop( ISoundSource* _source ) = 0;
        
        //
        // releases previously created sound source
        // -
        // precond:
        //   ISoundSystem context must be initialized
        //   _source must be in 'stopped' state
        // params:
        //   _source - non-null valid ISoundSource pointer returned by 'createSoundSource'
        // results:
        //   all resources assigned with ISoundSource are released
        //
        virtual void ReleaseSoundSource( ISoundSource* _source ) = 0;
    };
}   // namespace nane

#endif  // NANE_ISOUNDSYSTEM_H
